package com.jerry.ReadWriteLock;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 通过将控制变量封装在同一个控制器，并将控制器线程共享的方式，实现所有线程都监听同一个控制器中变量的状态，来进行对应的执行策略调整。
 *
 * 只要共享一个控制器，即可实现多种控制开关，即锁。这边读写锁其实是共享一个控制器来进行锁的作用的。可以加任意数量的锁。
 *
 * 这边的锁可以看做是对控制器中各种变量按某种线程运行逻辑构建的控制状态的算子。
 *
 * 这种将变量与逻辑处理剥离的做法，会让我们觉得申明变量困难。因为我们习惯把事物扁平化，看到总是二维图像。习惯用逻辑反向定义变量。
 *
 * 其实变量也是本身是存在于事物本身的，即使没有锁，这边读取和写入也会有读写数。只不过这些变量被我们忽略，而且有可能存在用不到的变量，我们需要进行发现并甄别，甄别过程中需要按照锁的需要进行抽取。
 */
public class ReadWriteTestCase {

  static  class ReadThread implements Runnable {

        private ReadWriteLock readWriteLock;

        private List<Integer> ints;

        public ReadThread(ReadWriteLock readWriteLock, List<Integer> ints) {
            this.readWriteLock = readWriteLock;
            this.ints = ints;
        }

        @Override
        public void run() {
           String threadName =  Thread.currentThread().getName();
            readWriteLock.getReadLock().lock();
            System.out.println("线程"+threadName+"开始读取");

            StringBuffer str = new StringBuffer();
            for(Integer i:ints){

                str.append(i+"_");
            }
            System.out.println("线程"+threadName+"打印当前值："+str.toString());
            System.out.println("线程"+threadName+"读取结束");

            readWriteLock.getReadLock().unlock();

        }
    }

    static class WriteThread implements Runnable {
        private ReadWriteLock readWriteLock;
        private  List<Integer> ints;

        public WriteThread(ReadWriteLock readWriteLock, List<Integer> ints) {
            this.ints = ints;
            this.readWriteLock = readWriteLock;
        }

        @Override
        public void run() {
            String threadName =  Thread.currentThread().getName();


            try {
                readWriteLock.getWriteLock().lock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("线程"+threadName+"开始写入");

            ints.add(new Random().nextInt());
            System.out.println("线程"+threadName+"写入结束");

            readWriteLock.getWriteLock().unlock();

        }
    }

    public static void main(String[] args) {
      //支持并发读不支持并发写
        ReadWriteLock readWriteLock = new ReadWriteLockImpl(true);
        List<Integer> ints = new ArrayList<>();
        for(int i = 0;i<10;i++) {
            WriteThread writeThread = new WriteThread(readWriteLock,ints);
            Thread thread = new Thread(writeThread,"WriteThread-"+i);
            thread.start();
        }
        for(int i = 0;i<10;i++) {
            ReadThread readThread = new ReadThread(readWriteLock,ints);
            Thread thread = new Thread(readThread,"ReadThread-"+i);
            thread.start();
        }

    }
}
